const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const del = require('del');
const gulpPlugins = require('gulp-load-plugins')();
const autoprefixer = require('autoprefixer');
const browserSync = require('browser-sync').create();
const loadData = require('./loadData');
const gulpConfig = require('./config');

const gulpConfigFilePath = path.join(process.cwd(), './gulp.config.js');

// 判断gulp配置文件是否存在
if (fs.existsSync(gulpConfigFilePath)) {
  Object.assign(gulpConfig, require(gulpConfigFilePath))
}

const clean = () => {
  return del([gulpConfig.destination,  gulpConfig.temp])
}

const styles = () => {
  return gulp
    .src(
      gulpConfig.paths.styles,
      {
        cwd: gulpConfig.src,
        base: gulpConfig.src,
        ignore: gulpConfig.ignore.styles,
      },
    )
    .pipe(gulpPlugins.plumber({ errorHandler: gulpPlugins.sass.logError }))
    .pipe(gulpPlugins.sass({ ...gulpConfig.sassOptions }))
    .pipe(
      gulpPlugins.postcss([
        autoprefixer({ ...gulpConfig.autoprefixerOptions })
      ])
    )
    .pipe(gulp.dest(gulpConfig.temp, { sourcemaps: true }))
    .pipe(browserSync.reload({ stream: true }))
}

const scripts = () => {
  return gulp.src(
    gulpConfig.paths.scripts,
    {
      cwd: gulpConfig.src,
      base: gulpConfig.src,
      ignore: gulpConfig.ignore.scripts,
    }
  )
    .pipe(gulpPlugins.plumber())
    .pipe(gulpPlugins.babel({ presets: ['@babel/preset-env'] }))
    .pipe(gulp.dest(gulpConfig.temp, { sourcemaps: true }))
    .pipe(browserSync.reload({ stream: true }))
}

const pages = () => {
  return gulp
    .src(
      gulpConfig.paths.pages,
      {
        cwd: gulpConfig.src,
        base: gulpConfig.src,
        ignore: gulpConfig.ignore.pages,
      }
    )
    .pipe(gulpPlugins.swig({ defaults: { cache: false },  data: loadData(`${gulpConfig.src}/data`) }))
    .pipe(gulp.dest(gulpConfig.temp))
}

const fonts = () => {
  return gulp
    .src(
      gulpConfig.paths.fonts,
      {
        cwd: gulpConfig.src,
        base: gulpConfig.src,
        ignore: gulpConfig.ignore.fonts,
      }
    )
    .pipe(gulpPlugins.imagemin({...gulpConfig.imageminOptions}))
    .pipe(gulp.dest(gulpConfig.destination))
}

const images = () => {
  return gulp.src(
    gulpConfig.paths.images,
    {
      cwd: gulpConfig.src,
      base: gulpConfig.src,
      ignore: gulpConfig.ignore.images,
      since: gulp.lastRun(images)
    }
  )
    .pipe(gulpPlugins.imagemin({...gulpConfig.imageminOptions}))
    .pipe(gulp.dest(gulpConfig.destination))
}

const extra = () => {
  return gulp
    .src(
      '**',
      {
        cwd: gulpConfig.public,
        base: gulpConfig.public,
        dot: true
      }
    )
    .pipe(gulp.dest(gulpConfig.destination))
}

const devServer = () => {
  gulp.watch(gulpConfig.paths.styles, { cwd: gulpConfig.src }, styles)
  gulp.watch(gulpConfig.paths.scripts, { cwd: gulpConfig.src }, scripts)
  gulp.watch(gulpConfig.paths.pages, { cwd: gulpConfig.src }, pages)
  gulp.watch('**', { cwd: gulpConfig.public }, browserSync.reload)

  browserSync.init({
    notify: false,
    port: 3000,
    open: false,
    server: {
      baseDir: [gulpConfig.temp, gulpConfig.src, gulpConfig.public],
      plugins: [`bs-html-injector?files[]=${gulpConfig.temp}/*.html`],
      routes: {
        '/node_modules': 'node_modules',
      }
    }
  })
}

const server = () => {
  browserSync.init({
    notify: gulpConfig.browserSyncNotify,
    port: gulpConfig.port,
    open: gulpConfig.browserSyncOpen,
    server: gulpConfig.destination
  })
}

const useRef = () => {
  return gulp
    .src(
      gulpConfig.paths.pages,
      {
        cwd: gulpConfig.temp,
        base: gulpConfig.temp,
        ignore: gulpConfig.ignore.pages
      }
    )
    .pipe(gulpPlugins.useref({ searchPath: ['.', '..'] }))
    .pipe(gulpPlugins.if(/\.js$/, gulpPlugins.uglify(gulpConfig.uglifyOptions)))
    .pipe(gulpPlugins.if(/\.css$/, gulpPlugins.cleanCss(gulpConfig.cleanCssOptions)))
    .pipe(gulpPlugins.if(/\.html$/, gulpPlugins.htmlmin(gulpConfig.htmlminOptions)))
    .pipe(gulpPlugins.revAll.revision({
      dontRenameFile: ['.html'],
      dontUpdateReference: ['.html'],
    }))
    .pipe(gulp.dest(gulpConfig.destination))
};

const compile = gulp.parallel(styles, scripts, pages)
const dev = gulp.series(clean, compile, devServer)
const build = gulp.series(
  clean,
  gulp.parallel(
    gulp.series(compile, useRef, () => del(gulpConfig.temp)),
    fonts,
    images,
    extra
  )
)
const start = gulp.series(build, server);

module.exports = {
  styles,
  clean,
  dev,
  build,
  start,
}
